package sv.com.seguros.dso.asg;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import sv.com.seguros.dso.BaseServiceImpl;
import sv.com.seguros.dto.asg.AsgAbono;
import sv.com.seguros.dto.asg.AsgPoliza;
import sv.com.seguros.exception.WebException;
import sv.com.seguros.web.util.WebUtilidades;

public class AsgPolizaServiceImpl extends BaseServiceImpl implements AsgPolizaService {
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = {Exception.class, WebException.class})
	public void createPoliza(AsgPoliza asgPoliza) throws WebException{
		createPoliza(asgPoliza, null);
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = {Exception.class, WebException.class})
	public void createPoliza(AsgPoliza asgPoliza, Long asgPolizaIdAnterior) throws WebException{
		try {
			boolean nuevaPoliza = asgPoliza.getAsgPolizaId() == null || asgPoliza.getAsgPolizaId() <= 0;
			Calendar calendar = Calendar.getInstance();
			AsgAbono asgAbono = null;
			int cantidadCuotas = Integer.parseInt(WebUtilidades.trimToZero(asgPoliza.getAsgPolizaCantidadCuota()));
			if(cantidadCuotas == 0) throw new WebException("La cantidad de cuotas debe ser mayor que cero");
			double cuota = 0.0;
			double cuotaInicial = Double.parseDouble(WebUtilidades.trimToZero(asgPoliza.getAsgPolizaCuotaInicial()));
			double cuotaFinal = 0.0;
			double remanente = Double.parseDouble(WebUtilidades.trimToZero(asgPoliza.getAsgPolizaPrima())) - cuotaInicial;
			if(cantidadCuotas > 1){
				cuota = remanente / Double.valueOf(cantidadCuotas - 1);
				cuota = Double.valueOf(WebUtilidades.decimalFormat2Decimals.format(cuota));
				if(cuota * (cantidadCuotas - 1) < remanente){
					cuotaFinal = remanente - cuota * (cantidadCuotas - 2); 
				}else cuotaFinal = cuota;
			}
			calendar.setTime(WebUtilidades.dateFormatAsYYYYMMDD.parse(asgPoliza.getAsgPolizaFechaInicio()));
			save(asgPoliza);
			if(nuevaPoliza){
				for(int i = 0; i < cantidadCuotas; i++){
					asgAbono = new AsgAbono();
					asgAbono.setAsgAbonoFechaLimite(WebUtilidades.dateFormatAsYYYYMMDD.format(calendar.getTime()));
					if(i == 0)
						asgAbono.setAsgAbonoMonto(WebUtilidades.decimalFormat2Decimals.format(Double.valueOf(cuotaInicial)));
					else if(i == cantidadCuotas - 1)
						asgAbono.setAsgAbonoMonto(WebUtilidades.decimalFormat2Decimals.format(Double.valueOf(cuotaFinal)));
					else
						asgAbono.setAsgAbonoMonto(WebUtilidades.decimalFormat2Decimals.format(Double.valueOf(cuota)));
					asgAbono.setAsgAbonoNumeroCuota(String.valueOf(i + 1));
					asgAbono.setAsgPoliza(asgPoliza);
					save(asgAbono);
					calendar.add(Calendar.MONTH, 1);
				}
			}
			if(asgPolizaIdAnterior != null && asgPolizaIdAnterior > 0){
				String hqlQuery = "update AsgPoliza set asgPolizaFechaRenovacion = :asgPolizaFechaRenovacion, asgPolizaRenovada = '1' where asgPolizaId = :asgPolizaId";
				Map<String, Object> parameters = new HashMap<String, Object>();
				parameters.put("asgPolizaFechaRenovacion", WebUtilidades.dateFormatAsYYYYMMDDHHMMSS.format(new Date()));
				parameters.put("asgPolizaId", asgPolizaIdAnterior);
				executeNonHibernateQuery(hqlQuery, parameters);
			}
		} catch (WebException e) {
			throw e;
		} catch (Exception e) {
			logger.error("Exception: ", e);
			throw new WebException("Problemas al tratar de guardar los datos de poliza");
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = {Exception.class, WebException.class})
	public void deleteAbono(AsgPoliza asgPoliza, Long asgAbonoId) throws WebException{
		try {
			Map<String, Object> parameters = new HashMap<String, Object>();
			String hqlQuery = "delete from AsgAbono where asgAbonoId = :asgAbonoId";
			parameters.put("asgAbonoId", asgAbonoId);
			executeNonHibernateQuery(hqlQuery, parameters);
			hqlQuery = "update AsgAbono set asgAbonoNumeroCuota = (asgAbonoNumeroCuota - 1) where asgAbonoId > :asgAbonoId and asgPolizaId = :asgPolizaId";
			parameters.put("asgPolizaId", asgPoliza.getAsgPolizaId());
			int cantidadCuotas = Integer.parseInt(WebUtilidades.trimToZero(asgPoliza.getAsgPolizaCantidadCuota()));
			cantidadCuotas--;
			if(cantidadCuotas < 0) cantidadCuotas = 0;
			asgPoliza.setAsgPolizaCantidadCuota(String.valueOf(cantidadCuotas));
			save(asgPoliza);
		} catch (Exception e) {
			throw new WebException("Problemas al tratar de eliminar el Abono");
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = {Exception.class, WebException.class})
	public void updateAbonos(List<AsgAbono> asgAbonos, AsgPoliza asgPoliza) throws WebException{
		try {
			int numeroCuota = 1;
			Date asgAbonoFechaLimite;
			for (AsgAbono asgAbono : asgAbonos){
				asgAbono.setAsgPoliza(asgPoliza);
				if(StringUtils.isBlank(asgAbono.getAsgAbonoNumeroCuota()) || 
						Integer.valueOf(WebUtilidades.trimToZero(asgAbono.getAsgAbonoNumeroCuota())) == 0)
					asgAbono.setAsgAbonoNumeroCuota(String.valueOf(numeroCuota));
				asgAbonoFechaLimite = WebUtilidades.dateFormatAsDD_MM_YYYY.parse(asgAbono.getAsgAbonoFechaLimite());
				asgAbono.setAsgAbonoFechaLimite(WebUtilidades.dateFormatAsYYYYMMDD.format(asgAbonoFechaLimite));
				save(asgAbono);
				numeroCuota++;
			}
			asgPoliza.setAsgPolizaCantidadCuota(String.valueOf(asgAbonos.size()));
			save(asgPoliza);
		} catch (Exception e) {
			throw new WebException("Problemas al tratar de actualizar el Detalle de Abonos");
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = {Exception.class, WebException.class})
	public void deleteAsgPoliza(Long asgPolizaId) throws Exception{
		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("asgPolizaId", asgPolizaId);
		String hqlQuery = "delete from AsgAbono where asgPoliza.asgPolizaId = :asgPolizaId";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgPago where asgPagoId not in (select asgPago.asgPagoId from AsgAbono)";
		executeNonHibernateQuery(hqlQuery, new HashMap<String, Object>());
		hqlQuery = "delete from AsgSeguimiento where asgReclamo.asgReclamoId in " +
				   "	(select asgReclamoId from AsgReclamo where asgPoliza.asgPolizaId = :asgPolizaId)";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgSeguimiento where asgPendiente.asgPendienteId in " +
		   "	(select asgPendienteId from AsgPendiente where asgPoliza.asgPolizaId = :asgPolizaId)";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgContacto where asgReclamo.asgReclamoId in " +
		   "	(select asgReclamoId from AsgReclamo where asgPoliza.asgPolizaId = :asgPolizaId)";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgContacto where asgPendiente.asgPendienteId in " +
		   "	(select asgPendienteId from AsgPendiente where asgPoliza.asgPolizaId = :asgPolizaId)";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgReclamo where asgPoliza.asgPolizaId = :asgPolizaId";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgPendiente where asgPoliza.asgPolizaId = :asgPolizaId";
		executeNonHibernateQuery(hqlQuery, parameters);
		hqlQuery = "delete from AsgPoliza where asgPolizaId = :asgPolizaId";
		executeNonHibernateQuery(hqlQuery, parameters);
	}

}
